#include "./spi/soft_spi.h"
#include "debug.h"

#define OPT_DBG_INF 1U

/*SPI Init*/
void Spi_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  
  SPI1_NSS_CLK_ENABLE();
  SPI1_CLK_CLK_ENABLE();
  SPI1_MISO_CLK_ENABLE();
  SPI1_MOSI_CLK_ENABLE();

  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull  = GPIO_PULLUP;
  GPIO_InitStruct.Pin   = SPI1_NSS_PIN;
  HAL_GPIO_Init(SPI1_NSS_PORT,&GPIO_InitStruct);

  GPIO_InitStruct.Pin   = SPI1_CLK_PIN;
  HAL_GPIO_Init(SPI1_CLK_PORT,&GPIO_InitStruct);

  GPIO_InitStruct.Pin   = SPI1_MOSI_PIN;
  HAL_GPIO_Init(SPI1_MOSI_PORT,&GPIO_InitStruct);
  
  GPIO_InitStruct.Mode  = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pin   = SPI1_MISO_PIN;
  HAL_GPIO_Init(SPI1_MISO_PORT,&GPIO_InitStruct);
  
  SPI1_NSS_H;
  #if SPI_MODE_0
  SPI1_CLK_L;
  #elif SPI_MODE_3
  SPI1_CLK_H;
  #endif
}

#if SPI_MODE_0
/*software spi write byte*/
void SpiWriteByte_Software(uint8_t c)
{
  SPI1_NSS_L;
  
  taskENTER_CRITICAL();
  
	for(uint32_t i = 0;i < 8; i++)
  {
		if(c & (uint8_t)0x80)
    {
      SPI1_MOSI_H;
    }
		else
    {
			SPI1_MOSI_L;
    }
		c <<= 0x1UL;
    
    __nop();__nop();__nop();__nop();
    SPI1_CLK_H;
    __nop();__nop();__nop();__nop();
    SPI1_CLK_L;
	}
  
  taskEXIT_CRITICAL();
  
  SPI1_NSS_H;
}

/*software spi read byte*/
uint8_t SpiReadByte_Software(void)
{
  uint8_t retData = 0;
  
  SPI1_NSS_L;
  
  taskENTER_CRITICAL();
  
	for(uint32_t i = 0;i < 8; i++)
  {
    SPI1_CLK_H;
    __nop();__nop();__nop();__nop();
    
		if(SPI1_MISO)
    {
      retData |= ((uint8_t)0x80 >> i);
    }
		else
    {
			retData &= (~((uint8_t)0x80 >> i));
    }
    
    SPI1_CLK_L;
    __nop();__nop();__nop();__nop();
	}
  
  SPI1_NSS_H;
  
  taskEXIT_CRITICAL();
  
  return retData;
}
#elif SPI_MODE_3
/*software spi write byte*/
void SpiWriteByte_Software(uint8_t c)
{
  SPI1_NSS_L;
  
  taskENTER_CRITICAL();

	for(uint32_t i = 0;i < 8; i++)
  {
    SPI1_CLK_L;
    
    if(c & (uint8_t)0x80)
    {
      SPI1_MOSI_H;
    }
		else
    {
			SPI1_MOSI_L;
    }
		c <<= 0x1UL;
    
    __nop();__nop();__nop();__nop();
    SPI1_CLK_H;
    __nop();__nop();__nop();__nop();
	}
  
  taskEXIT_CRITICAL();
  
  SPI1_NSS_H;
}

/*software spi read byte*/
uint8_t SpiReadByte_Software(void)
{
  uint8_t retData = 0;
  
  SPI1_NSS_L;
  
  taskENTER_CRITICAL();
  
	for(uint32_t i = 0;i < 8; i++)
  {
    SPI1_CLK_L;
    __nop();__nop();__nop();__nop();
    SPI1_CLK_H;
    __nop();__nop();__nop();__nop();
    
		if(SPI1_MISO)
    {
      retData |= ((uint8_t)0x80 >> i);
    }
		else
    {
			retData &= (~((uint8_t)0x80 >> i));
    }
	}
  
  SPI1_NSS_H;
  
  taskEXIT_CRITICAL();
  
  return retData;
}
#endif
